// Copyright (c) 2024 CHANGLEI. All rights reserved.

import 'package:charts_grasp/src/core/src/theme/charts_theme.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

class CgTheme extends StatelessWidget {
  const CgTheme({
    super.key,
    this.data,
    required this.child,
  });

  final Widget child;

  final CgThemeData? data;


  static CgThemeData of(BuildContext context) {
    final _InheritedTheme? inheritedTheme = context.dependOnInheritedWidgetOfExactType<_InheritedTheme>();
    return inheritedTheme?.data ??
        (Theme.of(context).colorScheme.brightness == Brightness.light ? CgThemeData.light() : CgThemeData.dark());
  }

  @override
  Widget build(BuildContext context) {
    return _InheritedTheme(data: data, child: child);
  }
}

class _InheritedTheme extends InheritedTheme {
  const _InheritedTheme({this.data, required super.child});

  final CgThemeData? data;

  @override
  bool updateShouldNotify(_InheritedTheme oldWidget) => data != oldWidget.data;

  @override
  Widget wrap(BuildContext context, Widget child) {
    final _InheritedTheme? ancestorTheme = context.findAncestorWidgetOfExactType<_InheritedTheme>();
    return identical(this, ancestorTheme) ? child : CgTheme(data: data, child: child);
  }
}

@immutable
class CgThemeData with Diagnosticable {
  factory CgThemeData({
    Brightness? brightness,
    CgChartThemeData? chartThemeData,
  }) {
    brightness ??= Brightness.light;
    chartThemeData = chartThemeData ?? CgChartThemeData(brightness: brightness);
    return CgThemeData.raw(
      brightness: brightness,
      chartThemeData: chartThemeData,
    );
  }

  const CgThemeData.raw({
    required this.brightness,
    required this.chartThemeData,
  });

  factory CgThemeData.light() => CgThemeData(brightness: Brightness.light);

  factory CgThemeData.dark() => CgThemeData(brightness: Brightness.dark);

  factory CgThemeData.fallback() => CgThemeData.light();

  final Brightness brightness;

  final CgChartThemeData chartThemeData;

  CgThemeData copyWith({
    Brightness? brightness,
    CgChartThemeData? chartThemeData,
  }) {
    return CgThemeData.raw(
      brightness: brightness ?? this.brightness,
      chartThemeData: chartThemeData ?? this.chartThemeData,
    );
  }

  // ignore: prefer_constructors_over_static_methods
  static CgThemeData lerp(CgThemeData? a, CgThemeData? b, double t) {
    assert(a != null);
    assert(b != null);

    return CgThemeData.raw(
      brightness: t < 0.5 ? a!.brightness : b!.brightness,
      chartThemeData: CgChartThemeData.lerp(a!.chartThemeData, b!.chartThemeData, t)!,
    );
  }

  @override
  bool operator ==(Object other) {
    if (other.runtimeType != runtimeType) {
      return false;
    }

    return other is CgThemeData && other.brightness == brightness && other.chartThemeData == chartThemeData;
  }

  @override
  int get hashCode {
    final List<Object> values = <Object>[
      brightness,
      chartThemeData,
    ];
    return Object.hashAll(values);
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    final CgThemeData defaultData = CgThemeData.fallback();
    properties.add(EnumProperty<Brightness>('brightness', brightness, defaultValue: defaultData.brightness));
    properties.add(DiagnosticsProperty<CgChartThemeData>('chartThemeData', chartThemeData,
        defaultValue: defaultData.chartThemeData,),);
  }
}
